import numpy as np
import scipy.interpolate as spi
import logging as log

# 日志格式化
log.basicConfig(format='%(asctime)s ---- [line:%(lineno)d] ---- %(levelname)s: %(message)s', level=log.DEBUG)


def _cubic_spline_all(data):
    """
    说明 样条差值函数的使用demo
    """
    # 得到原始数据长度
    data_length = len(data)
    # 创建空值下标数组
    none_array = []
    # 创建需要处理的y轴数据
    y_data = []
    #  X轴数据
    x_data = []

    # 首位为空的时候，赋值为该数组第一个不为空的数
    if data[0] is None:
        data = replenish_first_array(data)
        none_array.append(0)

    # 赋值末尾数字
    if data[data_length - 1] is None:
        data = replenish_last_array(data)
        none_array.append(data_length - 1)

    # 记录需要插值的数组下标，并去掉控值
    for data_index in range(0, len(data)):
        if data[data_index] is None:
            # 记录空值下标把是空值的数据添加进空值下标数组
            none_array.append(data_index)
        else:
            # 去掉none值的Y数据
            x_data.append(data_index)
            y_data.append(data[data_index])
    # 三个参数 起点为1，终点为数组长度，点数据所以步长为1，曲线数据步长为0.1
    # 定义X轴点数据
    x_point = np.arange(0, data_length, 1)

    # 生成三次样条拟合点
    # 根据观测点和样条参数，生成插值
    x_point_r = spi.splrep(x_data, y_data, k=3)
    y_point_r = spi.splev(x_point, x_point_r)
    for item in none_array:
        data[item] = round(y_point_r[item], 2)
    return data


def _cubic_spline(data):
    """
    只返回补上的数据
    :param data:
    :return:
    """
    if judge_array_all_none(data):
        #  都是空值不需要处理
        return None, None
    # 得到原始数据长度
    data_length = len(data)
    # 去掉末尾的None
    data = _delete_array_tail_none(data)
    # 创建空值下标数组
    none_index_array = []
    # 创建需要处理的y轴数据
    y_data = []
    #  X轴数据
    x_data = []
    #  定义返回数据数据
    spline_point_data = []
    # 首位为空的时候，赋值为该数组第一个不为空的数
    if data[0] is None:
        data = replenish_first_array(data)
        none_index_array.append(0)
        spline_point_data.append(data[0])

    # 记录需要插值的数组下标，并去掉控值
    for data_index in range(0, len(data)):
        if data[data_index] is None:
            # 记录空值下标把是空值的数据添加进空值下标数组
            none_index_array.append(data_index)
        else:
            # 去掉none值的Y数据
            x_data.append(data_index)
            y_data.append(data[data_index])
    if len(y_data) < 4:
        # 大于等于4才可以划画线
        return None, None
    #  判断需不需要处理
    if len(none_index_array) == len(data):
        #  都是空值不需要处理
        return None, None
    if len(none_index_array) == 0:
        # 没有空值
        return None, None

    # # 赋值末尾数字
    # if data[data_length - 1] is None:
    #     data = replenish_last_array(data)
    #     none_index_array.append(data_length - 1)
    #     spline_point_data.append(data[data_length - 1])
    # 三个参数 起点为1，终点为数组长度，点数据所以步长为1
    # 定义X轴点数据
    x_point = np.arange(0, data_length, 1)

    # 生成三次样条拟合点
    # 根据观测点和样条参数，生成插值
    x_point_r = spi.splrep(x_data, y_data, k=3)
    y_point_r = spi.splev(x_point, x_point_r)

    for item in none_index_array:
        spline_point_data.append(round(y_point_r[item], 2))
    return spline_point_data, none_index_array


def judge_array_all_none(array):
    """
    判断一个数组是否全部都是None值
    true 是
    false  有值
    :param array:
    :return:
    """
    for data in array:
        if data is not None:
            return False
    return True


def replenish_first_array(array):
    """
    补充数组首位元素来自于，本数组第一个不为空的数值
    :param array:
    :return:
    """
    for data_index in range(0, len(array)):
        if array[data_index] is not None:
            array[0] = array[data_index]
            return array
    return array


def replenish_last_array(array):
    """
    补充数组末位元素来自于，本数组倒数第一个不为空的数值
    :param array:
    :return:
    """
    for item in reversed(array):
        if item is not None:
            array[len(array) - 1] = item
            return array


def _delete_array_tail_none(array):
    """
    删除数组末尾的None值
    :param array: 数组
    :return: 去掉末尾空值的数据
    """
    # 新数组
    noNoneForArray = []
    # 倒叙临时数组
    temp = []
    # 判断是否为尾部
    isTail = True
    for item in reversed(array):
        if isTail:
            if item is not None:
                isTail = False
                temp.append(item)
        else:
            temp.append(item)
    for item in reversed(temp):
        noNoneForArray.append(item)
    return noNoneForArray
